package com.globallogic.javatrainings.sergiiivanov.controller;

import com.globallogic.javatrainings.sergiiivanov.model.Student;
import com.globallogic.javatrainings.sergiiivanov.model.University;
import com.globallogic.javatrainings.sergiiivanov.model.UniversityFailure;
import com.globallogic.javatrainings.sergiiivanov.model.UniversityWarning;
import com.globallogic.javatrainings.sergiiivanov.view.StudentDetailsPage;

class StudentDetailsController extends BasicController {

    private static final String FAILED_TO_ENROLL_STUDENT = "Failed to enroll student";

    private enum States {
        ASSIGN_TO_COURSE, SHOW_COURCES, SHOW_GENERAL_INFO, SHOW_RESUME, SHOW_SCORES
    }

    private StudentDetailsPage page = new StudentDetailsPage();
    private int command;
    private String[] courses = {};
    private States currentState;
    private Student student;
    private University university;

    StudentDetailsController(Student s) {
        this.student = s;
        currentState = States.SHOW_GENERAL_INFO;
    }

    @Override
    BasicController initiate(University u) throws UniversityFailure {
        university = u;
        if (currentState == States.SHOW_GENERAL_INFO) {
            return showStudentGeneralInfo();
        }
        if (currentState == States.SHOW_RESUME) {
            return showStudentResume();
        }
        if (currentState == States.SHOW_COURCES) {
            return showStudentCourses();
        }
        if (currentState == States.SHOW_SCORES) {
            return showStudentScore();
        }
        if (currentState == States.ASSIGN_TO_COURSE) {
            return enrollStudentToCourse();
        }

        return this;
    }

    private BasicController respondMainActions() {
        switch (command) {

        case 0:
            return null;
        case 1:
            currentState = States.SHOW_RESUME;
            return this;
        case 2:
            currentState = States.SHOW_COURCES;
            return this;
        case 3:
            currentState = States.SHOW_SCORES;
            return this;
        default:
            currentState = States.SHOW_GENERAL_INFO;
            return this;
        }
    }

    private void readCommand() {
        command = InputController.readInt();
    }

    private BasicController addNewResumeEntry() {
        String[] formFields = { "Year: ", "Summary: ", "Description: " };
        String[] newResumeRecord = new String[formFields.length];
        for (int i = 0; i < formFields.length; i++) {
            page.show(formFields[i]);
            newResumeRecord[i] = InputController.readString();
        }

        try {
            student.addResumeEntry(newResumeRecord);
        } catch (UniversityWarning e) {
            page.error("Failed to add resume record", e.getMessage());
        }
        return this;
    }

    private BasicController removeResumeEntry(int indexResumeRecord) throws UniversityFailure {
        try {
            student.removeResumeEntry(indexResumeRecord);
        } catch (UniversityWarning e) {
            page.error("Failed to remove resume entry", e.getMessage());
        }
        return this;
    }

    private BasicController enrollStudentToCourse() throws UniversityFailure {
        page.showAvailableCoursesList(university.courses.getCourses().toNamesList());
        readCommand();
        try {
            university.courses.getCourseByIndex(command).enrollStudent(student);
        } catch (UniversityWarning e) {
            page.error(FAILED_TO_ENROLL_STUDENT, e.getMessage());
        }
        currentState = States.SHOW_COURCES;
        return this;
    }

    private BasicController showStudentCourses() throws UniversityFailure {
        page.studentPageHeader(university.getTitle());
        page.studentMenu();
        page.showStudentCourses(student.getCoursesList().toNamesList());
        readCommand();
        if (command > 3 && command < (courses.length + page.menuOffset)) {
            try {
                student.getCoursesList().get(command - page.menuOffset).disenrollStudent(student);
            } catch (UniversityWarning e) {
                page.error("Failed to disenroll student", e.getMessage());
            }
            currentState = States.SHOW_COURCES;
            return this;
        }
        if (command == (courses.length + page.menuOffset)) {
            currentState = States.ASSIGN_TO_COURSE;
            return this;
        }
        return respondMainActions();
    }

    private BasicController showAverageScorePerDiscipline() throws UniversityFailure {
        page.studentPageHeader(university.getTitle());
        try {
            page.ShowAverageScores(student.getAverageScore());
        } catch (UniversityWarning e) {
            page.error("Failed to calculate average scores", e.getMessage());
        }
        readCommand();
        return this;
    }

    private BasicController showStudentGeneralInfo() {
        page.studentPageHeader(university.getTitle());
        page.pagePersonDetails(student.getName(), student.getMobile(), student.getEmail());
        page.studentMenu();
        readCommand();
        return respondMainActions();
    }

    private BasicController showStudentResume() throws UniversityFailure {
        String[][] resume = student.getResumePrint();
        page.studentPageHeader(university.getTitle());
        page.showResume(resume);
        page.studentMenu();
        readCommand();
        if (command == resume.length + page.menuOffset) {
            return addNewResumeEntry();
        }
        if (command >= page.menuOffset) {
            return removeResumeEntry(command - page.menuOffset);
        }
        return respondMainActions();
    }

    private BasicController showStudentScore() throws UniversityFailure {
        page.studentPageHeader(university.getTitle());
        page.pagePersonDetails(student.getName(), student.getMobile(), student.getEmail());
        page.ShowStudentScores(student.getScores());
        readCommand();
        if (command == 1) {
            return showAverageScorePerDiscipline();
        }
        currentState = States.SHOW_GENERAL_INFO;
        return this;
    }

}
